From 86ec3a9b477b95ff3acf1aa744932e0353047d41 Mon Sep 17 00:00:00 2001 From: Jimi Xenidis Date: Tue, 28 Nov 2006 18:46:13 -0500 Subject: [PATCH] [XEN][POWERPC] Fix IPI stall timeout without using timebase_freq When using the register dump feature of Xen, one will sometimes see a message about an IPI finish stall. This is because of an int to long comparison bug, so fix it by doing proper nanosecond based time accounting with no explicit reference to timebase_freq. Signed-off-by: Amos Waterland Signed-off-by: Jimi Xenidis Signed-off-by: Hollis Blanchard --HG-- extra : transplant_source : .%90%9Do%2A%B7g%FEW%23%A9%7E/T%13%F8v%16r%96 --- xen/arch/powerpc/smp.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/xen/arch/powerpc/smp.c b/xen/arch/powerpc/smp.c index 3d06b9afa0..4fb58afaef 100644 --- a/xen/arch/powerpc/smp.c +++ b/xen/arch/powerpc/smp.c @@ -90,7 +90,8 @@ int on_selected_cpus( int retry, int wait) { - int t, retval = 0, nr_cpus = cpus_weight(selected); + int retval = 0, nr_cpus = cpus_weight(selected); + unsigned long start, stall = SECONDS(1); spin_lock(&call_lock); @@ -104,19 +105,21 @@ int on_selected_cpus( send_IPI_mask(selected, CALL_FUNCTION_VECTOR); /* We always wait for an initiation ACK from remote CPU. */ - for (t = 0; atomic_read(&call_data.started) != nr_cpus; t++) { - if (t && t % timebase_freq == 0) { + for (start = NOW(); atomic_read(&call_data.started) != nr_cpus; ) { + if (NOW() > start + stall) { printk("IPI start stall: %d ACKS to %d SYNS\n", atomic_read(&call_data.started), nr_cpus); + start = NOW(); } } /* If told to, we wait for a completion ACK from remote CPU. */ if (wait) { - for (t = 0; atomic_read(&call_data.finished) != nr_cpus; t++) { - if (t > timebase_freq && t % timebase_freq == 0) { + for (start = NOW(); atomic_read(&call_data.finished) != nr_cpus; ) { + if (NOW() > start + stall) { printk("IPI finish stall: %d ACKS to %d SYNS\n", atomic_read(&call_data.finished), nr_cpus); + start = NOW(); } } } @@ -168,6 +171,11 @@ void smp_message_recv(int msg, struct cpu_user_regs *regs) #ifdef DEBUG_IPI static void debug_ipi_ack(void *info) { + if (info) { + unsigned long start, stall = SECONDS(5); + for (start = NOW(); NOW() < start + stall; ); + printk("IPI recv on cpu #%d: %s\n", smp_processor_id(), (char *)info); + } return; } @@ -175,12 +183,12 @@ void ipi_torture_test(void) { int cpu; unsigned long before, after, delta; - unsigned long min = ~0, max = 0, mean = 0, sum = 0, tick = 0; + unsigned long min = ~0, max = 0, mean = 0, sum = 0, trials = 0; cpumask_t mask; cpus_clear(mask); - while (tick < 1000000) { + while (trials < 1000000) { for_each_online_cpu(cpu) { cpu_set(cpu, mask); before = mftb(); @@ -192,12 +200,15 @@ void ipi_torture_test(void) if (delta > max) max = delta; if (delta < min) min = delta; sum += delta; - tick++; + trials++; } } - mean = sum / tick; + mean = tb_to_ns(sum / trials); + + printk("IPI latency: min = %ld ticks, max = %ld ticks, mean = %ldns\n", + min, max, mean); - printk("IPI tb ticks: min = %ld max = %ld mean = %ld\n", min, max, mean); + smp_call_function(debug_ipi_ack, "Hi", 0, 1); } #endif -- 2.30.2